package com.longqin.wechat.config;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.longqin.wechat.annotation.BusOperation;
import com.longqin.wechat.entity.Log;
import com.longqin.wechat.listener.SysLogEvent;
import com.longqin.wechat.util.OperationRecordEnum;

/**
 * 通用切面
 */
@Component
@Aspect
public class CommonAcpect {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	 @Autowired
	 private ApplicationContext applicationContext;
	 
	 // spel表达式解析器
	 private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
	 
	 // 参数名发现器
	 private DefaultParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
	 
	 @Pointcut("@annotation(com.longqin.wechat.annotation.BusOperation)")
	 public void busLog() {
		 
	 }
	
	/**
	 * @Description: 异步日志插入
	 * @param jp
	 * @param ret
	 * @throws Throwable
	 * @Author longqin
	 * @Date 2025-05-07
	 * 
	 */
	@AfterReturning(returning = "ret", pointcut = "busLog()")
	public void doBusAfterReturning(JoinPoint jp, Object ret) throws Throwable {
		Method proxyMethod = ((MethodSignature) jp.getSignature()).getMethod();
		Method soruceMethod = jp.getTarget().getClass().getMethod(proxyMethod.getName(),
							  proxyMethod.getParameterTypes());
		BusOperation oper = soruceMethod.getAnnotation(BusOperation.class);
		StringBuilder sBuilder = new StringBuilder();// 存储内容
		Object[] args = jp.getArgs();
		if(oper.recordType()==OperationRecordEnum.PARAM_TOSTRING){
			for (int i = 0; i < args.length; i++) 
				sBuilder.append(args[i].toString()).append("\n");
		}else if(oper.recordType()==OperationRecordEnum.DES){
			String[] parameterNames = parameterNameDiscoverer.getParameterNames(proxyMethod);
			 if (parameterNames != null && parameterNames.length > 0){
	            EvaluationContext context = new StandardEvaluationContext();
	            for (int i = 0; i < args.length; i++) {
	                context.setVariable(parameterNames[i],args[i]); // 替换spel里的变量值为实际值， 比如 #user -->  user对象
	            }
	            // 解析出实际的日志信息
	            String opeationInfo = spelExpressionParser.parseExpression(oper.des()).getValue(context).toString();
	        	sBuilder.append(opeationInfo);
	        }
		
		}else sBuilder.append(ret.toString());
		logger.info("插入系统日志:{}",JSON.toJSON(sBuilder));
		applicationContext.publishEvent(new SysLogEvent(new Log(oper.title(), oper.operationType().getCode(), sBuilder.toString())));//异步插入
	}
}
